package aggregate

import (
	"context"
	"time"

	"gitee.com/leonscript/sally/v2/domain/entity"
	"gorm.io/gorm"
)

// Reference 聚合所有仓储接口
type Reference interface {
	TX
	WorkflowRepository
	NodeRepository
	ReviewTaskRepository
	TimeoutNodeRepository
	TimeoutAlertRecordRepository
}

// TX 事物
type TX interface {
	// Begin 创建事物
	Begin() *gorm.DB
	Commit(tx *gorm.DB) error
	Rollback(tx *gorm.DB) error
}

// WorkflowRepository 工作流仓储接口
type WorkflowRepository interface {
	QueryWorkflowTemplateByID(ctx context.Context, id string) (result entity.WorkflowTemplate, err error)
	CreateWorkflowTemplateTX(ctx context.Context, workflowTemplate entity.WorkflowTemplate, tx *gorm.DB) (err error)
	CreateWorkflowTX(ctx context.Context, workflow entity.Workflow, tx *gorm.DB) (err error)
	QueryAndLockWorkflowByCondTX(ctx context.Context, cond QueryWorkflowCond, tx *gorm.DB) (result entity.Workflow, err error)
	UpdateWorkflow(ctx context.Context, workflow entity.Workflow) (err error)
	UpdateWorkflowTX(ctx context.Context, workflow entity.Workflow, tx *gorm.DB) (err error)
	QueryActivatedWorkflows(ctx context.Context, req GetWorkflowsRequest) (result []ActivatedWorkflow, total int64, err error)
	QueryWorkflowByID(ctx context.Context, id string) (result entity.Workflow, err error)
	DeleteWorkflowByCondTX(ctx context.Context, id string, tx *gorm.DB) (err error)
}

// NodeRepository 节点仓储接口
type NodeRepository interface {
	CreateNodeTX(ctx context.Context, node entity.Node, tx *gorm.DB) (err error)
	CreateNodeTemplateTX(ctx context.Context, nodeTemplate entity.NodeTemplate, tx *gorm.DB) (err error)
	CreateNodeTemplateReviewersTX(ctx context.Context, reviewers []entity.NodeTemplateReviewer, tx *gorm.DB) (err error)
	QueryNodeTemplateByID(ctx context.Context, id string) (result entity.NodeTemplate, err error)
	UpdateNodeTX(ctx context.Context, node entity.Node, tx *gorm.DB) (err error)
	QueryNodeTemplateReviewers(ctx context.Context, nodeTemplateID string) (result []entity.NodeTemplateReviewer, err error)
	QueryNodeByIDTX(ctx context.Context, id string, tx *gorm.DB) (result entity.Node, err error)
	DeleteNodeByCondTX(ctx context.Context, workflowID string, tx *gorm.DB) (err error)
	// QueryNodeTemplatesByWorkflowTemplateID 根据工作流模板ID查询所有节点模板
	QueryNodeTemplatesByWorkflowTemplateID(ctx context.Context, workflowTemplateID string) (result []entity.NodeTemplate, err error)
	// QueryNodesByWorkflowID 根据工作流ID查询所有节点
	QueryNodesByWorkflowID(ctx context.Context, workflowID string) (result []entity.Node, err error)

	// QueryNodeTemplateReviewersByNodeTemplateIDs 根据节点模板ID列表批量查询所有审批人
	QueryNodeTemplateReviewersByNodeTemplateIDs(ctx context.Context, nodeTemplateIDs []string) (result []entity.NodeTemplateReviewer, err error)

	// FindNextApprovalNodeRecursive 递归查找下一个审批节点
	// 从指定的节点模板开始，根据条件参数递归查找下一个需要审批的节点模板
	// 参数:
	//   - ctx: 上下文对象
	//   - currentNodeTemplateID: 当前节点模板ID
	//   - conditionParams: 条件参数，用于条件路由判断
	//   - visitedNodes: 已访问的节点集合，用于循环引用检测
	//   - depth: 当前递归深度
	//   - maxDepth: 最大递归深度限制
	// 返回值:
	//   - nextNodeTemplateID: 下一个审批节点模板ID，空字符串表示已到达工作流末尾
	//   - err: 错误信息
	FindNextApprovalNodeRecursive(ctx context.Context, currentNodeTemplateID string, conditionParams entity.ConditionParams, visitedNodes map[string]bool, depth, maxDepth int) (nextNodeTemplateID string, err error)
}

// ReviewTaskRepository 审批任务仓储接口
type ReviewTaskRepository interface {
	CreateReviewerTasksTX(ctx context.Context, reviewerTasks []entity.NodeReviewerTask, tx *gorm.DB) (err error)
	QueryReviewerTaskByID(ctx context.Context, id string) (result entity.NodeReviewerTask, err error)
	UpdateNodeReviewerTaskTX(ctx context.Context, nodeReviewerTask entity.NodeReviewerTask, tx *gorm.DB) (err error)
	UpdateNodeReviewerTaskByCondTX(ctx context.Context, cond, nodeReviewerTask entity.NodeReviewerTask, tx *gorm.DB) (err error)
	QueryNodeReviewTasks(ctx context.Context, req GetNodeReviewTasksRequest) (result []NodeReviewTask, total int64, err error)
	QueryNodeReviewTasksTX(ctx context.Context, req GetNodeReviewTasksRequest, tx *gorm.DB) (result []NodeReviewTask, err error)
	DeleteNodeReviewerTaskByCondTX(ctx context.Context, workflowID string, tx *gorm.DB) (err error)
	// QueryNodeReviewerTasksByNodeIDTX 根据节点ID查询所有审批任务
	QueryNodeReviewerTasksByNodeIDTX(ctx context.Context, nodeID string, tx *gorm.DB) (result []entity.NodeReviewerTask, err error)
	// QueryNodeReviewerTaskByIDTX 根据任务ID查询审批任务（事务版本）
	QueryNodeReviewerTaskByIDTX(ctx context.Context, id string, tx *gorm.DB) (result entity.NodeReviewerTask, err error)
}

// TimeoutNodeInfo 超时节点信息
// 包含节点、工作流和工作流模板的相关信息
type TimeoutNodeInfo struct {
	// 节点信息
	NodeID        string    `json:"nodeId"`
	NodeStatus    int       `json:"nodeStatus"`
	NodeCreatedAt time.Time `json:"nodeCreatedAt"`

	// 工作流信息
	WorkflowID string `json:"workflowId"`

	// 工作流模板信息
	WorkflowTemplateID string `json:"workflowTemplateId"`
	TimeoutAlertHours  int    `json:"timeoutAlertHours"`
}

type QueryWorkflowCond struct {
	ReviewerTaskID string
	WorkflowID     string
}

// TimeoutNodeWithTasks 超时节点及其审批任务信息
// 通过一次查询获取节点和相关审批任务的完整信息，避免N+1查询问题
type TimeoutNodeWithTasks struct {
	// 节点信息
	NodeID        string    `json:"nodeId"`
	NodeStatus    int       `json:"nodeStatus"`
	NodeCreatedAt time.Time `json:"nodeCreatedAt"`

	// 工作流信息
	WorkflowID string `json:"workflowId"`

	// 工作流模板信息
	WorkflowTemplateID string `json:"workflowTemplateId"`
	TimeoutAlertHours  int    `json:"timeoutAlertHours"`

	// 审批任务信息
	TaskID     string `json:"taskId"`
	ReviewerID string `json:"reviewerId"`
	TaskStatus int    `json:"taskStatus"`
}

// TimeoutNodeRepository 超时节点仓储接口
type TimeoutNodeRepository interface {
	// QueryTimeoutNodes 查询超时节点
	// 查询所有超时的节点信息，用于超时提醒功能
	// 参数:
	//   - ctx: 上下文
	// 返回值:
	//   - result: 超时节点信息列表
	//   - err: 错误信息
	QueryTimeoutNodes(ctx context.Context) (result []TimeoutNodeInfo, err error)

	// QueryTimeoutNodesWithTasks 查询超时节点及其任务
	// 查询所有超时的节点及其关联的审核任务信息
	// 参数:
	//   - ctx: 上下文
	// 返回值:
	//   - result: 超时节点及任务信息列表
	//   - err: 错误信息
	QueryTimeoutNodesWithTasks(ctx context.Context) (result []TimeoutNodeWithTasks, err error)
}

// TimeoutAlertRecordRepository 超时提醒记录仓储接口
type TimeoutAlertRecordRepository interface {
	// CheckTimeoutAlertRecords 批量检查节点是否已发送提醒
	// 查询指定工作流下的节点提醒记录状态
	// 参数:
	//   - ctx: 上下文
	//   - nodeIDs: 节点ID列表
	//   - workflowID: 工作流ID
	// 返回值:
	//   - result: 节点ID到是否已提醒的映射，true表示已提醒
	//   - err: 错误信息
	CheckTimeoutAlertRecords(ctx context.Context, nodeIDs []string, workflowID string) (result map[string]bool, err error)

	// CreateTimeoutAlertRecord 创建超时提醒记录
	// 使用UPSERT方式创建或更新提醒记录，确保幂等性
	// 参数:
	//   - ctx: 上下文
	//   - nodeID: 节点ID
	//   - workflowID: 工作流ID
	// 返回值:
	//   - err: 错误信息
	CreateTimeoutAlertRecord(ctx context.Context, nodeID, workflowID string) (err error)

	// BatchCreateTimeoutAlertRecords 批量创建超时提醒记录
	// 批量插入多个节点的提醒记录，提高性能
	// 参数:
	//   - ctx: 上下文
	//   - nodeIDs: 节点ID列表
	//   - workflowID: 工作流ID
	// 返回值:
	//   - err: 错误信息
	BatchCreateTimeoutAlertRecords(ctx context.Context, nodeIDs []string, workflowID string) (err error)
}
